<html>
<head>
<title>Sensor Data Overlay - VDO.Ninja</title>
<meta charset="UTF-8">
<style>
body{
	padding:0;
	margin:0;
	background-color: #0000;
}
iframe {
	border:0;
	margin:0;
	padding:0;
	display:block;
}

#vdoninja {
	width:100%;
	height:100%;
}

#container {
	border:0;
	margin:0;
	padding:0;
	display:block;
	width:100%;
	height:100%;
	position:absolute;
	top:0;
	left:0;
	
}

#overlay{
	border:0;
	margin:0;
	padding:0;
	display:block;
	text-align:right;
	position:absolute;
	top:100px;
	right:0;
	z-index: 10;
    color: white;
	font-size:300%;
}

#canvas{
	border:0;
	margin:0;
	padding:0;
	display:block;
	width:20%;
	text-align:right;
	height:100px;
	position:absolute;
	top:0;
	right:0;
	z-index: 5;
}

</style>
</head>
<body id="main">
	<div id="overlay"></div>
	<canvas id="canvas"></canvas>
	<div id="container"></div>
		<div id="map-container" style="position: relative;">
		<iframe 
			id="mapFrame" 
			src="your_map_url" 
			width="600" 
			height="450" 
			style="position: absolute; top: 0; left: 0; border: 0; width: 600px; height: 450px; display:none;">
		</iframe>
		<div style="position: absolute; top: 0; left: 0; width: 600px; height: 450px; z-index: 10; cursor: default;">
		</div>
		<span id="marker" style="position: absolute; top: 50px; left: 50%; transform: translate(-50%, calc(-50% - 15px)); font-size: 30px;display:none;">📍</span>
		</div>
	</div>
<script>
function getColor(value) {
  var hue = (Math.abs(value*100+50)).toString(10);
  return ["hsl(", hue, ",100%,50%)"].join("");
}
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var height = context.canvas.height;
var width = context.canvas.width;
canvas.history_accel = [];
canvas.history_speed = [];
var canvasNew = true

function plotData(speed, accel) { 


	canvas.history_accel.push(accel);
	canvas.history_speed.push(speed);

	canvas.history_accel = canvas.history_accel.slice(-1 * canvas.width);
	canvas.history_speed = canvas.history_speed.slice(-1 * canvas.width);
	
	var maxSpeed = Math.max(...canvas.history_speed);
	
	var interval = 10;
	var target = canvas.target || (interval*1.5);
	if (target && (maxSpeed > target)){
		
		canvas.target = maxSpeed*1.5; // set it higher than it needs to be, so it doens't jump around a lot
		var yScale = height / canvas.target;
		context.clearRect(0, 0, width, height);
		var w = 1;
		var x = width - w;
		
		
		for (var i = 0; i<canvas.history_speed.length;i++){
			
			var accel = canvas.history_accel[i];
			var speed = canvas.history_speed[i];
			
			var val = (10-accel)/10;
			if (val>1){val=1;}
			else if (val<0){val=0;}
			var color = getColor(val);
			var y = height - speed * yScale;
			context.fillStyle = color;
			context.fillRect(x, y, w, height);
			context.fillStyle = "#DDD5";
			context.fillRect(x, y-2, w, 4);
			
			if (y-5>0){
				context.fillStyle = "#FFF3";
				context.fillRect(x, y+2, w, 1);
			}

			var imageData = context.getImageData(w, 0, x, height);
			context.putImageData(imageData, 0, 0);
			context.clearRect(x, 0, w, height);
		}
		
		for (var tt = interval; tt<canvas.target;tt+=interval){
			var y = parseInt(height - tt * yScale);
			context.fillStyle = "#0555";
			context.fillRect(0, y, width, 1);
		}
		return;
	}
	
	var val = (10-accel)/10;
	if (val>1){val=1;}
	else if (val<0){val=0;}
	var color = getColor(val);

	var yScale = height / target;

	var w = 1;
	var x = width - w;
	var y = height - speed * yScale;
	
	context.fillStyle = color;
	context.fillRect(x, y, w, height);
	context.fillStyle = "#DDD5";
	context.fillRect(x, y-2, w, 4);
	
	if (y-5>0){
		context.fillStyle = "#FFF3";
		context.fillRect(x, y+2, w, 1);
	}
	
	context.fillStyle = "#0555";
	if (canvasNew){
		canvasNew = false;
		for (var tt = interval; tt<target;tt+=interval){
			var y = parseInt(height - tt * yScale);
			context.fillRect(0, y, width, 1);
		}
	} else {
		for (var tt = interval; tt<target;tt+=interval){
			var y = parseInt(height - tt * yScale);
			context.fillRect(x, y, w, 1);
		}
	}
	
	var imageData = context.getImageData(w, 0, x, height);
	context.putImageData(imageData, 0, 0);
	context.clearRect(x, 0, w, height);
	
}

function loadIframe(url=false){ 
	var iframe = document.createElement("iframe");
	
	if (url){
		var iframesrc = url;
	} else {
		var iframesrc = document.getElementById("viewlink").value;
	}
	
	iframe.allow = "autoplay;camera;microphone;fullscreen;picture-in-picture;";

	if (iframesrc==""){
		iframesrc="./";
	}
	
	iframe.src = iframesrc;
	iframe.id = "vdoninja";
	
	document.getElementById("container").appendChild(iframe);
	var outputWindow = document.getElementById("overlay");

	var sensors = {};
	
	////////////  LISTEN FOR EVENTS

	var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
	var eventer = window[eventMethod];
	var messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message";

	var mapBounds = null;
	
	function calculateBBox(lat, lon) {
		// Calculate bounding box (bbox) based on the new latitude and longitude
		// This requires some geographic calculations to ensure the map is centered
		// and zoomed appropriately around the new marker position.
		var delta = 0.05; // Determines the zoom level. Smaller delta = higher zoom
		
		mapBounds = {};
		mapBounds.left = lon - delta;
		mapBounds.bottom = lat - delta;
		mapBounds.right = lon + delta;
		mapBounds.top = lat + delta;
		
		return `${mapBounds.left},${mapBounds.bottom},${mapBounds.right},${mapBounds.top},`;
	}
	
	function isMarkerOutsideMapBounds(markerLat, markerLon) {
		if (!mapBounds){return true;}
		return (
			markerLon < mapBounds.left ||
			markerLon > mapBounds.right ||
			markerLat < mapBounds.bottom ||
			markerLat > mapBounds.top
		);
	}
	
	function convertLatLngToPixel(lat, lon, mapBounds, mapWidth, mapHeight) {
		// Calculate the range of the map in both dimensions
		var lonRange = mapBounds.right - mapBounds.left;
		var latRange = mapBounds.top - mapBounds.bottom;

		// Calculate the position of the latitude and longitude relative to the map bounds
		var relativeX = (lon - mapBounds.left) / lonRange;
		var relativeY = (mapBounds.top - lat) / latRange; // Invert latitude because screen coordinates go top to bottom

		// Convert these relative positions into pixel values
		var x = relativeX * mapWidth;
		var y = relativeY * mapHeight;

		return { x: x, y: y };
	}
	
	function updateMap(lat, lon) {
		var iframemap = document.getElementById('mapFrame');
		iframemap.style = "filter: invert(90%)";
		var src = 'https://www.openstreetmap.org/export/embed.html?bbox='  + calculateBBox(lat, lon) + '&layer=mapnik';
		iframemap.src = src;
		iframemap.onload = function(){
			iframemap.style.display = "block";
			document.getElementById("marker").style.display = "block";
		}
	}
	
	function updateMarkerPosition(lat, lon) {
	
		if (isMarkerOutsideMapBounds(lat,lon)) {
			updateMap(lat, lon); // Function to load a new map image
		}
		
		// Convert lat, lon to pixel coordinates
		var mapWidth = 600; // Width of your map in pixels
		var mapHeight = 450; // Height of your map in pixels

		var pixelCoords = convertLatLngToPixel(lat, lon, mapBounds, mapWidth, mapHeight);

		// Update marker position
		var marker = document.getElementById("marker");
		marker.style.left = pixelCoords.x + 'px';
		marker.style.top = pixelCoords.y + 'px';

		// Check if marker is outside the current map bounds
		
	}

	eventer(messageEvent, function (e) {
		if (e.source != iframe.contentWindow){return} // reject messages send from other iframes
		
		if ("sensors" in e.data){
			//console.log(e.data.sensors);
			
			var speed = 0;
			var lat = null;
			var lon = null;
			if (e.data.sensors.pos){
				speed = e.data.sensors.pos.speed;
				lat = e.data.sensors.pos.lat || null;
				lon = e.data.sensors.pos.lon || null;
				// e.data.sensors.pos.alt
				// e.data.sensors.pos.t
			}
			
			
			if (isNaN(speed)) {
				speed = 0;
			}
			
			var accel = 0;
			if (e.data.sensors.lin){
				accel += Math.pow(e.data.sensors.lin.x, 2);
				accel += Math.pow(e.data.sensors.lin.y, 2);
				accel += Math.pow(e.data.sensors.lin.z, 2);
			}
			if (accel){
				accel = Math.pow(accel,0.5);
			}
			
			if (isNaN(accel)){
				accel = 0;
			}
			
			plotData(speed, accel);
			
			outputWindow.innerHTML = "";
			
			speed = parseInt(speed*100)/100;
			outputWindow.innerHTML += "speed: "+speed+"m/s<br />";          
		
			accel = parseInt(accel*100)/100;
			outputWindow.innerHTML += "acceleration: " + accel + "m/s^2<br />";        

			if ((lat!==null) && (lon!==null)){
				updateMarkerPosition(lat, lon);
			}
			
			
			//for (var key in e.data.sensors.lin) {
			//	outputWindow.innerHTML += key + " lin: " +  e.data.sensors.lin[key] + "<br />";           
			//}
			//for (var key in e.data.sensors.acc) {
			//	outputWindow.innerHTML += key + " acc: " +  e.data.sensors.acc[key] + "<br />";           
			//}
			//for (var key in e.data.sensors.mag) {
			//	outputWindow.innerHTML += key + " magnet: " +  e.data.sensors.mag[key] + "<br />";         
			//}
			//for (var key in e.data.sensors.ori) {
			//	outputWindow.innerHTML += key + " orientation: " +  e.data.sensors.ori[key] + "<br />";         
			//}
		}
	});
}

loadIframe("../"+window.location.search);

</script>
</body>
</html>
